﻿using System;
using System.Globalization;
using JetBrains.Annotations;
using JetBrains.DocumentModel;
using JetBrains.ReSharper.Daemon;
using JetBrains.ReSharper.Daemon.Impl;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Resolve;
using JetBrains.ReSharper.Psi.Tree;

namespace GammaJul.ReSharper.GammaXaml.Highlightings.Xaml {

	/// <summary>
	/// An highlighting that adds a gutter mark indicating that a XAML field declaration with a x:Name is bound to a data context method.
	/// </summary>
	public abstract class CaliburnBoundMarkOnGutter : IHighlightingWithRange {
		private readonly ITreeNode _element;
		private readonly IReference _reference;
		
		[NotNull]
		public IReference Reference {
			get { return _reference; }
		}

		public bool IsValid() {
			return _element.IsValid() && _reference.IsValid();
		}

		public string ToolTip {
			get {
				IDeclaredElement element = _reference.Resolve().DeclaredElement;
				string qualifiedName;
				string kind;
				if (element != null) {
					qualifiedName = DeclaredElementPresenter.Format(element.PresentationLanguage, DeclaredElementPresenter.QUALIFIED_NAME_PRESENTER, element);
					kind = DeclaredElementPresenter.Format(element.PresentationLanguage, DeclaredElementPresenter.KIND_PRESENTER, element);
				}
				else {
					qualifiedName = "???";
					kind = "???";
				}
				return String.Format(CultureInfo.CurrentCulture, "Bound by Caliburn.Micro to {0} '{1}' (click to navigate)", kind, qualifiedName);
			}
		}

		public string ErrorStripeToolTip {
			get { return ToolTip; }
		}

		public int NavigationOffsetPatch {
			get { return 0; }
		}

		public DocumentRange CalculateRange() {
			return _element.GetHighlightingRange();
		}

		protected CaliburnBoundMarkOnGutter([NotNull] ITreeNode element, [NotNull] IReference reference) {
			if (element == null)
				throw new ArgumentNullException("element");
			if (reference == null)
				throw new ArgumentNullException("reference");

			_element = element;
			_reference = reference;
		}

	}

}